import React from 'react';
import { CURRENT } from './renderAuthorize';
// eslint-disable-next-line import/no-cycle
import PromiseRender from './PromiseRender';

export type IAuthorityType =
    | undefined
    | string
    | string[]
    | Promise<boolean>
    | ((currentAuthority: string | string[]) => IAuthorityType);

/**
 * 通用方法判断是否有权限，不支持异步
 * @param authority
 * @param currentAuthority
 * @return boolean
 */
const hasPermissions = (authority: IAuthorityType, currentAuthority: string | string[] = CURRENT): boolean => {
    // 没有判定权限.默认查看所有
    // Retirement authority, return target;
    if (!authority) {
        return true;
    }
    // 数组处理
    if (Array.isArray(authority)) {
        if (Array.isArray(currentAuthority)) {
            if (currentAuthority.some(item => authority.includes(item))) {
                return true;
            }
        } else if (authority.includes(currentAuthority)) {
            return true;
        }
        return false;
    }
    // string 处理
    if (typeof authority === 'string') {
        if (Array.isArray(currentAuthority)) {
            if (currentAuthority.some(item => authority === item)) {
                return true;
            }
        } else if (authority === currentAuthority) {
            return true;
        }
        return false;
    }
    // Function 处理
    if (typeof authority === 'function') {
        try {
            const bool = authority(currentAuthority);
            if (bool) {
                return true;
            }
            return false;
        } catch (error) {
            throw error;
        }
    }
    throw new Error('unsupported parameters');
};

/**
 * 通用权限检查方法
 * Common check permissions method
 * @param { 权限判定 | Permission judgment } authority
 * @param { 你的权限 | Your permission description } currentAuthority
 * @param { 通过的组件 | Passing components } target
 * @param { 未通过的组件 | no pass components } Exception
 */
const checkPermissions = <T, K>(
    authority: IAuthorityType,
    currentAuthority: string | string[],
    target: T,
    Exception: K
): T | K | React.ReactNode => {
    // 没有判定权限.默认查看所有
    // Retirement authority, return target;
    if (!authority) {
        return target;
    }
    // 数组处理
    if (Array.isArray(authority)) {
        if (Array.isArray(currentAuthority)) {
            if (currentAuthority.some(item => authority.includes(item))) {
                return target;
            }
        } else if (authority.includes(currentAuthority)) {
            return target;
        }
        return Exception;
    }
    // string 处理
    if (typeof authority === 'string') {
        if (Array.isArray(currentAuthority)) {
            if (currentAuthority.some(item => authority === item)) {
                return target;
            }
        } else if (authority === currentAuthority) {
            return target;
        }
        return Exception;
    }
    // Promise 处理
    if (authority instanceof Promise) {
        return <PromiseRender<T, K> ok={target} error={Exception} promise={authority} />;
    }
    // Function 处理
    if (typeof authority === 'function') {
        try {
            const bool = authority(currentAuthority);
            // 函数执行后返回值是 Promise
            if (bool instanceof Promise) {
                return <PromiseRender<T, K> ok={target} error={Exception} promise={bool} />;
            }
            if (bool) {
                return target;
            }
            return Exception;
        } catch (error) {
            throw error;
        }
    }
    throw new Error('unsupported parameters');
};

export { checkPermissions, hasPermissions };

function check<T, K>(authority: IAuthorityType, target: T, Exception: K): T | K | React.ReactNode {
    return checkPermissions<T, K>(authority, CURRENT, target, Exception);
}

export default check;
